package distributedbank.server;

import distributedbank.RequestThread;
import distributedbank.Wrapper;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.HashMap;

/**
 * A BankBranch object represents a branch of the bank with a branchId. The
 * branch contains several accounts. Most of the methods in a BankBranch object
 * must be thread-safe, since BankBranch objects are shared across multiple
 * Threads.
 */
public class BankBranch
{
    private int serverId;

    private HashMap<Integer, Account> accounts;

    public BankBranch( int serverId ) {
        this.serverId = serverId;
        accounts = new HashMap<Integer, Account>();
    }

    /**
     * Returns the Account object with the given accountId. If no account with
     * the given account id exists, a new account with zero balance will be
     * returned.
     * 
     * @threadsafe
     */
    public Account getAccount( int accountId ) {
        synchronized( accounts ) {
            if( accounts.containsKey( accountId ) ) {
                return accounts.get( accountId );
            } else {
                // the requested account doesn't exist, so we create a new
                // account with zero balance.
                Account emptyAccount = new Account();
                accounts.put( accountId, emptyAccount );
                return emptyAccount;
            }
        }
    }

    /**
     * Starts listening for connections on a socket on the specified port. For
     * every incoming connection, a new Server object is created to deal with
     * the message.
     */
    public void runServer() {
        Wrapper wrapper = new Wrapper();
        try {
            // make ports unique by using the unique server id: each
            // primary/backup server has its own unique id
            ServerSocket serverSocket = new ServerSocket( Wrapper.basePort
                    + serverId );
            while( true ) {
                Socket clientSocket = serverSocket.accept();
                new RequestThread( this, clientSocket, wrapper ).start();
            }
        } catch( IOException e ) {
            System.out.println( e );
        }
    }
}